/*
 * Copyright 2023, Haiku, Inc.
 * Distributed under the terms of the MIT License.
 */

#include "DisassemblerLoongArch64.h"

#include <new>

#include <OS.h>

#include "CpuStateLoongArch64.h"
#include "InstructionInfo.h"


struct DisassemblerLoongArch64::DisassemblerData {
	// 指令解码器状态
	size_t offset;
	// 这里可以添加特定于LoongArch64的解码器数据结构
};


DisassemblerLoongArch64::DisassemblerLoongArch64()
	:
	fAddress(0),
	fCode(NULL),
	fCodeSize(0),
	fDisassemblerData(NULL)
{
}


DisassemblerLoongArch64::~DisassemblerLoongArch64()
{
	delete fDisassemblerData;
}


status_t
DisassemblerLoongArch64::Init(target_addr_t address, const void* code, size_t codeSize)
{
	// 清除旧数据
	delete fDisassemblerData;
	fDisassemblerData = NULL;

	// 设置新数据
	fDisassemblerData = new(std::nothrow) DisassemblerData;
	if (fDisassemblerData == NULL)
		return B_NO_MEMORY;

	fAddress = address;
	fCode = (const uint8*)code;
	fCodeSize = codeSize;

	// 初始化解码器
	fDisassemblerData->offset = 0;
	// 这里可以添加特定于LoongArch64的解码器初始化代码

	return B_OK;
}


status_t
DisassemblerLoongArch64::GetNextInstruction(BString& line, target_addr_t& _address,
	target_size_t& _size, bool& _breakpointAllowed)
{
	// 检查是否还有足够的代码可以解析
	if (fDisassemblerData->offset >= fCodeSize)
		return B_ENTRY_NOT_FOUND;

	const uint8* buffer = fCode + fDisassemblerData->offset;
	target_addr_t address = fAddress + fDisassemblerData->offset;

	// TODO: 实现LoongArch64指令解码
	// 这里需要添加LoongArch64指令解码逻辑
	// 暂时使用一个简单的实现，假设所有指令长度为4字节
	size_t instructionLength = 4;

	// 检查是否有足够的字节可以解码
	if (fDisassemblerData->offset + instructionLength > fCodeSize)
		return B_ENTRY_NOT_FOUND;

	// 更新偏移量
	fDisassemblerData->offset += instructionLength;

	// 生成十六进制表示
	char hexString[32];
	char* srcHex = hexString;
	for (size_t i = 0; i < instructionLength; i++) {
		sprintf(srcHex, "%02" PRIx8, buffer[i]);
		srcHex += 2;
	}

	// TODO: 实现指令格式化
	// 这里需要添加LoongArch64指令格式化逻辑
	// 暂时使用一个简单的实现，只显示十六进制数据
	line.SetToFormat("0x%016" B_PRIx64 ": %16.16s  <未实现的LoongArch64指令>", 
		address, hexString);

	_address = address;
	_size = instructionLength;
	_breakpointAllowed = true;

	return B_OK;
}


status_t
DisassemblerLoongArch64::GetPreviousInstruction(target_addr_t nextAddress,
	target_addr_t& _address, target_size_t& _size)
{
	if (nextAddress < fAddress || nextAddress > fAddress + fCodeSize)
		return B_BAD_VALUE;

	// 重置解码器状态
	fDisassemblerData->offset = 0;

	// 循环直到找到目标指令
	while (true) {
		target_addr_t currentAddress = fAddress + fDisassemblerData->offset;
		
		// 如果已经到达或超过目标地址，则返回错误
		if (currentAddress >= nextAddress)
			return B_ENTRY_NOT_FOUND;

		// 保存当前位置作为可能的前一条指令
		target_addr_t prevAddress = currentAddress;
		size_t prevOffset = fDisassemblerData->offset;

		// TODO: 实现LoongArch64指令解码
		// 暂时使用一个简单的实现，假设所有指令长度为4字节
		size_t instructionLength = 4;

		// 更新偏移量
		fDisassemblerData->offset += instructionLength;
		currentAddress = fAddress + fDisassemblerData->offset;

		// 如果下一条指令的地址等于目标地址，则找到了前一条指令
		if (currentAddress == nextAddress) {
			_address = prevAddress;
			_size = instructionLength;
			return B_OK;
		}
	}
}


status_t
DisassemblerLoongArch64::GetNextInstructionInfo(InstructionInfo& _info,
	CpuState* state)
{
	// 检查是否还有足够的代码可以解析
	if (fDisassemblerData->offset >= fCodeSize)
		return B_ENTRY_NOT_FOUND;

	const uint8* buffer = fCode + fDisassemblerData->offset;
	target_addr_t address = fAddress + fDisassemblerData->offset;

	// TODO: 实现LoongArch64指令解码和分析
	// 这里需要添加LoongArch64指令解码和分析逻辑
	// 暂时使用一个简单的实现，假设所有指令长度为4字节
	size_t instructionLength = 4;

	// 检查是否有足够的字节可以解码
	if (fDisassemblerData->offset + instructionLength > fCodeSize)
		return B_ENTRY_NOT_FOUND;

	// 更新偏移量
	fDisassemblerData->offset += instructionLength;

	// 设置指令信息
	_info.SetTo(address, instructionLength);
	_info.SetType(INSTRUCTION_TYPE_OTHER);
	// TODO: 根据指令类型设置正确的指令类型和目标地址

	return B_OK;
}